﻿using App.Extension;
using Microsoft.AspNetCore.SignalR.Client;
using Newtonsoft.Json;
using Simple.BasicNet.Core;
using Simple.BasicNet.Core.Configuration;
using Simple.BasicNet.Core.Net;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

/*********************************************************
 * 命名空间 App.Client
 * 接口名称 Client
 * 开发人员：11920
 * 创建时间：2023/4/26 9:06:29
 * 描述说明：
 * 更改历史：
 * 
 * *******************************************************/
namespace App.Client
{
	internal class Client: IClient
	{
		private IConnection connection;

		private ConcurrentDictionary<string, IConnection> ChildrenConnections;

		private HubConnection SignalR;

		IConfiguration configution;
		ILogger logger;
		public Client(IConfiguration configution,ILogger logger)
		{
			ChildrenConnections = new ConcurrentDictionary<string, IConnection>();
			this.configution = configution;
			this.logger = logger;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="SN"></param>
		/// <param name="connection"></param>
		public void AddChildren(string SN,IConnection connection)
		{
			if (!ChildrenConnections.ContainsKey(SN))
			{
				ChildrenConnections.TryAdd(SN,connection);
			}
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="SN"></param>
		public void AddChildren(string SN)
		{
			if (ChildrenConnections.ContainsKey(SN))
			{
				ChildrenConnections.TryRemove(SN,out IConnection connection);
			}
		}
		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public async Task CreateIignalRConneciont()
		{
			IDTContext context= connection.Context.GetContext<IDTContext>();
			if (string.IsNullOrWhiteSpace(context.Device.SN))
			{
				return;
			}
			var data = JsonConvert.SerializeObject(new
			{
				cmd = context.CurrentPack.CommandID,
				data = new
				{
					DeviceSn = context.Device.SN,
					Manufacturer = context.Device.Manufacture,
					Version = context.Device.WareVersion,
					ProductType = context.Device.ProductType,
					ParentDeviceID = context.Device.ParentDeviceID,
					AuthorizeKey = context.Device.AuthorizeKey,
					IsRelogin = context.Device.IsRelogin
				}
			});// GetDeviceInfo();
			if (SignalR != null)
			{
				if (!string.IsNullOrEmpty(context.Device.SN))
				{
					if (SignalR.State == HubConnectionState.Connected)
					{
						context.SendSignalR(data);
					}
				}
			}

			else
			{
				if (context.CurrentPack.CommandID == 16 || context.CurrentPack.CommandID == 20)
				{
					var ptype = context.GetPType();
					if (ptype != 64 && ptype != 65)
					{
						return;
					}
					int clientType = ptype == 64 ? 4 : 5;
					var groupName = context.Device.SN;
					if (clientType == 4)
					{
						groupName = context.Device.ParentDeviceID; // jobject["data"]["ParentDeviceID"].ToString();
					}

					var SignalRServer = configution.GetConfiguration<IDTConfiguration>().SignalRServerAddress;// "http://172.16.1.128:9003/signalr/dtm";
					Uri uri = new Uri($"{configution.GetConfiguration<IDTConfiguration>().SignalRServerAddress}?clientType={clientType}&clientName={context.Device.SN}&groupName={groupName}&relogin={context.Device.IsRelogin}");
					SignalR = new HubConnectionBuilder().WithUrl(uri)
						   .WithAutomaticReconnect(new RandomRetryPolicy(20, SignalRServer, context.Device.SN, logger))
						   .Build();

					CommandRecive(context);

					Connected();

					DisConnect();

					ReceiveMessage();

					DisConnected();

					Error();

					try
					{
						await SignalR.StartAsync();

						if (!string.IsNullOrWhiteSpace(data))
						{
							if (SignalR.State == HubConnectionState.Connected)
							{
								context.SendSignalR(data);
							}
							else
							{
								logger.Info($"{SignalR.State}");
							}
						}
					}
					catch (Exception ex)
					{
						logger.Info($"signalr连接失败：{ex.Message}");
						await SignalR.StartAsync();
					}
				}
				//else
				//{
				//    socketConnectionHandler.RemoveSocket(deviceSn);
				//}
			}
			return;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="data"></param>
		public void SendSignalR(string data)
		{
			IDTContext context = connection.Context.GetContext<IDTContext>();
			switch (context.Device.eProductType)
			{
				case eProductType.SendTable:
					SignalR.SendAsync("CommandRecive", context.Device.SN, data).Wait();
					break;
				case eProductType.Table:
					SignalR.SendAsync("TableCommandRecive", context.Device.SN, data).Wait();
					break;
				default:
					break;
			}
		}
		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public IConnection GetConnection()
		{
			return connection;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public ConcurrentDictionary<string,IConnection> GetChildrenConnections()
		{
			return ChildrenConnections;
		}
		/// <summary>
		/// 
		/// </summary>
		private void Connected()
		{
			SignalR.On<int, int, string>("Connected", (isOnline, clientType, message) => {
				if (isOnline == 1)
					logger.Info(message);
			});
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="context"></param>
		private void CommandRecive(IDTContext context)
		{
			SignalR.On<string, string>("CommandRecive", (sn, message) => {

				string commandId = "";
				//var socket = socketConnectionHandler.GetSocketById(sn);
				logger.Info($"沙盘号{sn}");
				var byteData = context.GetServerToClientData(message, ref commandId);
				context.AddCommand(commandId, new Command()
				{
					buffer = byteData,
					sendTime = DateTime.Now,
					status = 0,
					resendCount = 1,
				});
				context.Send(byteData);
				logger.Info(message);
			});
		}
		/// <summary>
		/// 
		/// </summary>
		private void DisConnected()
		{
			SignalR.On<string>("DisConnected", async (msg) =>
			{
				await SignalR.StopAsync();
				logger.Info($"signalr连接失败{msg}");
			});
			
		}
		/// <summary>
		/// 
		/// </summary>
		private  void DisConnect()
		{
			SignalR.On("DisConnect",async () =>
			{
				await SignalR.StopAsync();
			});
			
		}
		/// <summary>
		/// 
		/// </summary>
		private void ReceiveMessage()
		{
			SignalR.On<string, string>("ReceiveMessage", (user, message) => { 
			logger.Info(message);
			});
		}
		/// <summary>
		/// 
		/// </summary>
		private void Error()
		{
			SignalR.Closed += (ex) =>
			{
				logger.Error(ex.Message);
				logger.Error(ex.StackTrace);
				logger.Error("SignalR close!");
				return Task.CompletedTask;
			};
		}


	}
}
